import axios from 'axios'
import { BASE_URL, TIME_OUT } from './config'
import useLoadStore from '@/pinia/load'
import type { AxiosInstance, AxiosError } from 'axios'
import type { WrapAxiosDefaults, ConfigOrUrl, Result } from './request'
export enum Method {
  GET = 'GET',
  POST = 'POST',
  DELETE = 'DELETE',
  PUT = 'PUT'
}
class NetWork {
  instance: AxiosInstance
  constructor(config: WrapAxiosDefaults) {
    this.instance = axios.create(config)
    // 注册全局拦截器
    this.instance.interceptors.request.use(
      (config) => {
        if (isOverlay.value == false) {
          loadStore.sync_update_isOverlay(true)
        }
        return config
      },
      (err: AxiosError) => {
        if (isOverlay.value == true) {
          loadStore.sync_update_isOverlay(false)
        }

        return Promise.reject(err)
      }
    )
    this.instance.interceptors.response.use(
      (res) => {
        if (isOverlay.value == true) {
          loadStore.sync_update_isOverlay(false)
        }
        return res.data
      },
      (err: AxiosError) => {
        if (isOverlay.value == true) {
          loadStore.sync_update_isOverlay(false)
        }
        const content = this.throwError(err)
        Snackbar({ content, type: 'error' })
        return Promise.reject(err.response)
      }
    )
    //从config取出的拦截器是对应的实例的拦截器
    this.instance.interceptors.request.use(config.interceptors?.reqSuccessful, config.interceptors?.reqFailure)
    this.instance.interceptors.response.use(config.interceptors?.resSuccessful, config.interceptors?.resFailure)
  }
  private throwError(err: AxiosError) {
    let message = ''
    switch (err.response!.status) {
      case 400:
        message = '请求错误(400)'
        break
      case 401:
        message = '未授权，请重新登录(401)'
        // 这里可以做清空storage并跳转到登录页的操作
        break
      case 403:
        message = '拒绝访问(403)'
        break
      case 404:
        message = '请求出错(404)'
        break
      case 408:
        message = '请求超时(408)'
        break
      case 500:
        message = '服务器错误(500)'
        break
      case 501:
        message = '服务未实现(501)'
        break
      case 502:
        message = '网络错误(502)'
        break
      case 503:
        message = '服务不可用(503)'
        break
      case 504:
        message = '网络超时(504)'
        break
      case 505:
        message = 'HTTP版本不受支持(505)'
        break
      default:
        message = `连接出错(${err.response!.status})!`
    }
    return message
  }

  private request<R = any>(config: WrapAxiosDefaults) {
    return new Promise<Result<R>>((resolve, reject) => {
      if (config.interceptors?.reqSuccessful) {
        config = config.interceptors.reqSuccessful(config)
      }
      return this.instance.request<Result<R>, Result<R>>(config).then((res) => {
        if (config.interceptors?.resSuccessful) {
          res = config.interceptors?.resSuccessful(res)
        }
        resolve(res)
      }, reject)
    })
  }
  private transverter<T>(configOrUrl: ConfigOrUrl<T>, config?: WrapAxiosDefaults) {
    if (typeof configOrUrl === 'string') {
      config = config || {}
      config.url = configOrUrl
    } else {
      config = configOrUrl || {}
    }
    return config
  }

  get<R = any>(configOrUrl: ConfigOrUrl, config?: WrapAxiosDefaults) {
    const mergeConfig = this.transverter(configOrUrl, config)
    return this.request<R>({ ...mergeConfig, method: Method.GET })
  }
  post<R = any>(configOrUrl: ConfigOrUrl, config?: WrapAxiosDefaults) {
    const mergeConfig = this.transverter(configOrUrl, config)
    return this.request<R>({ ...mergeConfig, method: Method.POST })
  }
  delete<R = any>(configOrUrl: ConfigOrUrl, config?: WrapAxiosDefaults) {
    const mergeConfig = this.transverter(configOrUrl, config)
    return this.request<R>({ ...mergeConfig, method: Method.DELETE })
  }
  put<R = any>(configOrUrl: ConfigOrUrl, config?: WrapAxiosDefaults) {
    const mergeConfig = this.transverter(configOrUrl, config)
    return this.request<R>({ ...mergeConfig, method: Method.PUT })
  }
}

const loadStore = useLoadStore()
const { isOverlay } = storeToRefs(loadStore)
export const server = new NetWork({
  baseURL: BASE_URL,
  timeout: TIME_OUT
})
export default server
